﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif
#if WINDOWS
using Microsoft.Xna.Framework.Storage;
#endif
using Microsoft.Xna.Framework.Media;
using Neat;
using Neat.MenuSystem;
using Neat.EasyMenus;
using Neat.GUI;
using Neat.Mathematics;
using Neat.Graphics;
using System.IO;
namespace RiverRaidX
{
    public partial class RiverRaidGame : Screen
    {
        const float thres = 6;
        void UpdateGauge()
        {
            float fr = (float)fuel / (float)maxFuel;
            if (fr < 0) fr = 0;
            float pos = fuelBg.Position.X + 3;
            float width = game.GetTexture(fuelBg.BackgroundImage).Width - 6 - fuelArrow.Size.X;
            fuelArrow.Position = new Vector2(pos + fr * width, fuelBg.Position.Y + 3);
        }

        int shotInARow = 0;
        int last1up = 0;
        int level = 0;
        public override void Behave(GameTime gameTime)
        {
            #region Load next level if there is nothing else from current level to show
            if (outerWalls.Count == 0 || (outerWalls[outerWalls.Count - 1].Y + yOffset > 0 && levelPaths.Count > lastLoadedLevel))
            {
                level++;
                game.Console.WriteLine("Level " + lastLoadedLevel.ToString() + " loaded.");
                if (lastLoadedLevel + 1 >= levelPaths.Count) lastLoadedLevel = -1;
                if (level >= levelPaths.Count)
                {
                    lastLoadedLevel = game.RandomGenerator.Next(levelPaths.Count - 1);
                }
                try
                {
                    /*if (level % 2 == 0)
                        LoadLevel(levelPaths[++lastLoadedLevel]);
                    else
                        LoadRandom();*/
                    LoadLevel(levelPaths[++lastLoadedLevel]);
                    game.Console.Run("et_echo Level " + level + " loaded.");
                }
                catch (Exception e)
                {
                    game.Console.WriteLine(e.Message);
                    LoadLevel(levelPaths[lastLoadedLevel=0]);
                }
            }
            #endregion

            int center = game.GameWidth / 2;
            playerMesh.GetPositionAndSize(out pPos, out pSize);

            #region Death Code
            if (state == GameStates.DeathAnimation && !NoPlayer) //1
            {
                deathFrame--;
                if (deathFrame < 0)
                {
                    Reborn();
                }
                engineInstance.Stop();
                if (fuelInstance.State == SoundState.Playing) engineStartInstance.Stop();
            }
            #endregion
            #region Start Animation Code
            else if (state == GameStates.StartAnimation) //-1
            {
                engineInstance.Stop();
                if (engineStartInstance.State != SoundState.Playing && !NoPlayer)
                    engineStartInstance.Play();
                
                yOffset += ySpeed * speedBoostRate;
                
                var yS = game.GameHeight - 100 - Form.GetControl("dashboard").Size.Y;
                var yO = -pPos.Y + yS;
                if (yOffset >= yO)
                {
                    state = GameStates.Game; //state++;
                }

                for (int i = 0; i < entities.Count; i++)
                {
                    entities[i].Mesh = Polygon.BuildRectangle(entities[i].Position.X,
                            entities[i].Position.Y, entities[i].Size.X, entities[i].Size.Y);
                }
            }
            #endregion
            else
            {
                #region Game Code
                //Play low fuel sound
                if (fuel < maxFuel * 0.25f && !NoPlayer)
                {
                    if (staticInstance.State != SoundState.Playing) staticInstance.Play();
                    staticInstance.Pitch = (float)(Math.Sin(fuel * 0.06981317f));
                }
                else
                {
                    if (staticInstance.State == SoundState.Playing) staticInstance.Stop();
                }

                //Align the camera
                var yStart = game.GameHeight - 100 - Form.GetControl("dashboard").Size.Y;
                yOffset = -pPos.Y + yStart;
                    
                engineInstance.Pitch = MathHelper.Clamp(boostVec.Y/-ySpeed - 1.0f,-1.0f, 1.0f);
                    
                //FLYING CODE
                if (engineInstance.State != SoundState.Playing && !NoPlayer)
                {
                    engineInstance.Play();
                }

                if (!NoPlayer)
                {
                    fuel -= fuelUseRate;
                    if (fuel <= 0) Die();
                }

                lastRocketPos = rocketPos;

                #region Move the rocket
                if (rocketLaunched)
                {
                    rocketY -= rocketSpeed;
                    if (rocketY + yOffset < 0)
                    {
                        rocketLaunched = false;
                        shotInARow = 0;
                    }
                }

                Polygon rocket = Polygon.BuildRectangle(
                    (pSize.X - rocketSize.X) / 2 + pPos.X,
                    rocketY,
                    rocketSize.X, 2 * rocketSize.Y + rocketSpeed);

                rocketPos = new Vector2((pSize.X - rocketSize.X) / 2 + pPos.X, rocketY);
                #endregion
                if (!NoPlayer)
                {
                    #region For each entity check
                    float d;
                    bool isRefueling = false;
                    for (int i = 0; i < entities.Count; i++)
                    {
                        d = entities[i].Position.Y + entities[i].Size.Y + yOffset;
                        if (d > 0)
                        {
                            //Remove the entity if it is outside the viewport
                            if (d > game.GameHeight)
                            {
                                entities.RemoveAt(i);
                                continue;
                            }

                            #region Move entities if they are awake
                            if (pPos.Y < entities[i].WakeUpDistance + entities[i].Position.Y && currentLevel >= 1)
                                entities[i].Position.X += entities[i].Speed * (entities[i].Flip ? -1 : 1);

                            if (entities[i].Position.X < 0) entities[i].Position.X = game.GameWidth - 1;
                            else if (entities[i].Position.X > game.GameWidth) entities[i].Position.X = 1;
                            #endregion

                            entities[i].Mesh = Polygon.BuildRectangle(
                                entities[i].Position.X + entities[i].Size.X * (1.0f - collisionThreshold.X),
                                entities[i].Position.Y + entities[i].Size.Y * (1.0f - collisionThreshold.Y),
                                entities[i].Size.X * collisionThreshold.X,
                                entities[i].Size.Y * collisionThreshold.Y);

                            #region Player touches an object?
                            if (entities[i].ItemType == Items.Fuel)
                            {
                                entities[i].Mesh = Polygon.BuildRectangle(entities[i].Position.X,
                                    entities[i].Position.Y, entities[i].Size.X, entities[i].Size.Y);
                                if (Polygon.Collide(entities[i].Mesh, playerMesh))
                                {
                                    isRefueling = true;
                                    //FUEL
                                    if (fuel >= maxFuel)
                                    {
                                        fuel = maxFuel;
                                    }
                                    else
                                    {
                                        fuel = Math.Min(8 * fuelUseRate + fuel, maxFuel);
                                    }

                                    fuelInstance.Pitch = MathHelper.Clamp(((fuel * 2.0f) / maxFuel) - 1.0f, -1.0f, 1.0f);
                                    if (fuelInstance.State != SoundState.Playing) fuelInstance.Play();
                                }
                            }
                            else if (Polygon.Collide(entities[i].Mesh, playerMesh) && !NoPlayer) { KillEntity(i);  Die(); break; }
                            
                            #endregion

                            #region Rocket touches an entity
                            if (rocketLaunched && Polygon.Collide(entities[i].Mesh, rocket))
                            {
                                //EXPLOSION CODE
                                score += entities[i].ScorePoints;
                                if (entities[i].ItemType == Items.Bridge)
                                {
                                    currentLevel++;
                                    blinkFrame = blinkTime;
                                }

                                if (!entities[i].Immortal)
                                {
                                    KillEntity(i);
                                }
                                shotInARow++;
                                rocketLaunched = false;


                                if (shotInARow > 0 && shotInARow % 10 == 0)
                                {
                                    score += shotInARow * 100;
                                    game.TextEffects.Echo(shotInARow + " in a row!");
                                }
                            }
                            #endregion

                            //Stop the fueling sfx if player is not touching a FUEL entity
                            if (!isRefueling && fuelInstance.State == SoundState.Playing && !NoPlayer)
                                fuelInstance.Stop();
                        }
                    }
                    #endregion
                    #region Check collisions with walls
                    foreach (var item in walls)
                    {
                        //If rocket collides with a wall, destroy it
                        if (rocketLaunched)
                        {
                            if (Polygon.Collide(rocket, item))
                            {
                                shotInARow = 0;
                                rocketLaunched = false;
                            }
                        }
                        //If the player touches a wall, it dies
                        if (Polygon.Collide(item, playerMesh))
                        {
                            Die();
                            break;
                        }
                        //If entities touch walls, flip their directions
                        for (int i = 0; i < entities.Count; i++)
                        {
                            var e = entities[i];
                            Vector2 MTD;
                            if (!e.NoClip)
                            {
                                if (Polygon.Collide(e.Mesh, item, out MTD))
                                {
                                    e.Position += MTD;
                                    e.Flip = !e.Flip;
                                }
                            }
                        }
                    } //end foreach
                    #endregion
                }
                #endregion
            }//end if

            if (score - last1up > extraLifeScore && !NoPlayer)
            {
                last1up = ((int)(score / extraLifeScore) * extraLifeScore);
                lives++;
                game.TextEffects.Echo("1UP!");
            }

            #region Handle Messages
            if (state == GameStates.Game && !NoPlayer)
            {
                var t = (float)gameTime.ElapsedGameTime.Milliseconds * 0.002f;
                if (Messages.Contains(GameMessages.ShootRocket) && !rocketLaunched)
                {
                    game.PlaySound("launch");
                    rocketLaunched = true;
                    rocketY = pPos.Y - rocketSize.Y - 1;
                }
                else
                {
                    if (Messages.Contains(GameMessages.MoveLeft) || Messages.Contains(GameMessages.MoveRight))
                    {
                        if (Messages.Contains(GameMessages.MoveLeft) && Messages.Contains(GameMessages.MoveRight)) pxVel = 0;
                        else if (Messages.Contains(GameMessages.MoveLeft)) { if (pxVel > 0) pxVel = 0; pxVel -= xForce * t; }
                        else
                        //if (Messages.Contains(GameMessages.MoveRight)) 
                        { if (pxVel < 0) pxVel = 0; pxVel += xForce * t; }
                    }
                    else pxVel = 0;
                }
                boostVec = new Vector2(pxVel * t, -ySpeed *
                    (Messages.Contains(GameMessages.SpeedUp) ? speedBoostRate :
                    (Messages.Contains(GameMessages.SlowDown) ? 1 / speedBoostRate : 1)));
                playerMesh.Offset(boostVec);
                pxVel *= dampCoEf;

                
            }
            Messages.Clear();
            #endregion

            Form.Visible = !NoPlayer;
            base.Behave(gameTime);
        }

        void KillEntity(int i)
        {
            game.PlaySound(entities[i].ExplodeSound, 1.0f, (float)(game.RandomGenerator.NextDouble() * 2.0f - 1.0f));
            deadEntities.Add(entities[i]);
            entities.RemoveAt(i);
        }
    }
}